package ua.pp.bizon.yandex.uploader.remote;

import ua.pp.bizon.yandex.api.IAppService;
import ua.pp.bizon.yandex.api.IHTTPUtils;
import ua.pp.bizon.yandex.api.ObjectLookup;
import ua.pp.bizon.yandex.uploader.atom.AppLink;
import ua.pp.bizon.yandex.uploader.atom.EntryAlbum;

import java.io.StringReader;
import java.io.UnsupportedEncodingException;

import org.apache.abdera.model.Element;
import org.apache.abdera.parser.ParseException;
import org.apache.abdera.parser.stax.FOMParser;
import org.apache.abdera.util.Constants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpException;
import org.apache.http.entity.StringEntity;
import org.apache.http.protocol.HTTP;

public class RemoteAlbumFactory {
	public static final String CONTENT_TYPE_ALBUM = "application/atom+xml; charset=utf-8; type=entry";
	private static final String PARENT_ALBUM = EntryAlbum.PARENT;
	private static final String SELF = EntryAlbum.SELF;
	private static final Log LOG = LogFactory.getLog(RemoteAlbumFactory.class);

	/**
	 * create new album in root
	 * 
	 * @param to
	 * @return
	 * @throws HttpException
	 */
	public EntryAlbum createAlbum(String to) throws HttpException {
		LOG.debug("create folder: " + to);
		EntryAlbum res = createAlbum0(to);
		return res;
	}

	/**
	 * create new album in parent
	 * 
	 * @param folder
	 * @param parent
	 * @return
	 * @throws HttpException
	 */
	public EntryAlbum createAlbum(String folder, EntryAlbum parent) {
		EntryAlbum rezult = createAlbum0(folder);
		String toLink = parent.getLink(SELF).getLink();
		rezult = moveAlbum(rezult, toLink);
		return rezult;
	}

	/**
	 * remove album by AppLink url
	 * 
	 * @param url
	 * @return true if album removed
	 * @throws HttpException
	 */
	public boolean removeAlbum(AppLink url) throws HttpException {
		LOG.debug("remove path:" + url);
		return ObjectLookup.lookup(IHTTPUtils.class).remove(url);
	}

	private EntryAlbum create(String entry, AppLink albumsLink) {
		LOG.trace("Entry:" + entry);
		String post = null;
		do {
			try {

				post = ObjectLookup.lookup(IHTTPUtils.class).post(new StringEntity(entry, HTTP.UTF_8), albumsLink, CONTENT_TYPE_ALBUM, null);
			} catch (HttpException ex) {
				LOG.warn("exception occured while create new album, retry", ex);
			} catch (ParseException e) {
				LOG.warn(e.getMessage(), e);
			} catch (UnsupportedEncodingException e) {
				LOG.warn(e.getMessage(), e);
			}
		} while (post == null);
		return deserializeEntry(post);
	}

	private EntryAlbum createAlbum0(String to) {
		String entry = createEntry(to);
		AppLink albumsLink = ObjectLookup.lookup(IAppService.class).get().getAlbumsLink();
		return create(entry, albumsLink);
	}

	private String createEntry(String to) {
		return "<entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:f=\"yandex:fotki\">\r\n" + "<title>" + to + "</title>\r\n" + "<summary>" + to
				+ "</summary>\r\n" + "<f:password value=\"test\"/>\r\n" + "</entry>\r\n";
	}

	private EntryAlbum deserializeEntry(String post) {
		return new EntryAlbum(new FOMParser().parse(new StringReader(post)).getRoot());
	}

	protected EntryAlbum moveAlbum(EntryAlbum album, String toLink) {
		AppLink link = album.getLink(SELF);
		Element e = null;
		if (album.getLink(PARENT_ALBUM) == null) {
			e = album.getElement().getFactory().newElement(Constants.LINK, album.getElement());
		} else {
			e = album.getLink(PARENT_ALBUM).getElement();
			e.removeAttribute("href");
			e.removeAttribute("rel");
		}
		e.setAttributeValue("href", toLink);
		e.setAttributeValue("rel", PARENT_ALBUM);
		String response = null;
		do {
			try {
				response = ObjectLookup.lookup(IHTTPUtils.class).put(album.getElement().toString(), link);
			} catch (HttpException ex) {
				LOG.warn("exception occured while move new album, retry", ex);
			}
		} while (response == null);
		return deserializeEntry(response);
	}
}
